package org.ofbiz.sys.utils;

import static org.ofbiz.base.util.UtilIO.UTF8;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.RandomStringUtils;
import org.ofbiz.base.util.GeneralRuntimeException;
import org.ofbiz.base.util.UtilValidate;

//import com.jeecms.common.web.Constants;

public class PayUtil {
    
    /**
     * SHA加密
     * 
     * @param param
     * @param key
     * @return
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     */
    public static String createSha256(Map<String, String> param, String key) {
	String encdeStr = "";
	try {
	    // 签名步骤二：加上key
	    String str  = getParamsStr(param, key);
	    // 步骤三：加密并大写
	    encdeStr = cryptBytes("SHA-256", key, str.getBytes("UTF-8"));
	} catch (UnsupportedEncodingException e) {
	    e.printStackTrace();
	}
	return encdeStr;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static String getParamsStr(Map<String, String> param, String key) {
	// 签名步骤一：按字典排序参数
	List list = new ArrayList(param.keySet());
	Object[] ary = list.toArray();
	Arrays.sort(ary);
	list = Arrays.asList(ary);
	String str = "";
	for (int i = 0; i < list.size(); i++) {
	    str += list.get(i) + "=" + param.get(list.get(i) + "") + "&";
	}
	// 签名步骤二：加上key
	str += "key=" + key;
	return str;
    }

    /**
     * sha加密
     * 
     * @param hashType
     * @param key
     * @param bytes
     * @return
     */
    public static String cryptBytes(String hashType, String key, byte[] bytes) {
	if (hashType == null) {
	    hashType = "SHA-256";
	}
	//大写
	key = RandomStringUtils.random(new SecureRandom().nextInt(15) + 1, key).toUpperCase();

	StringBuilder sb = new StringBuilder();
	sb.append("$").append(hashType).append("$").append(key).append("$");
	String d = getCryptedBytes(hashType, key, bytes).toUpperCase();
	System.out.println("d========" + d);
	sb.append(d);
	return sb.toString();
    }

    public static String getCryptedBytes(String hashType, String salt, byte[] bytes) {
	try {
	    MessageDigest messagedigest = MessageDigest.getInstance(hashType);
	    messagedigest.update(salt.getBytes(UTF8));
	    messagedigest.update(bytes);
            String sign = Base64.encodeBase64URLSafeString(messagedigest.digest()).replace('+', '.').toUpperCase();
            System.out.println("sign=="+sign);
	    return sign;
	} catch (NoSuchAlgorithmException e) {
	    throw new GeneralRuntimeException("Error while comparing password", e);
	}
    }

    public static boolean doComparePosix(String crypted, byte[] bytes) {
	int typeEnd = crypted.indexOf("$", 1);
	int saltEnd = crypted.indexOf("$", typeEnd + 1);
	String hashType = crypted.substring(1, typeEnd);
	String salt = crypted.substring(typeEnd + 1, saltEnd);
	String hashed = crypted.substring(saltEnd + 1);
	return hashed.equals(getCryptedBytes(hashType, salt, bytes));
    }

    /**
     * 微信支付签名sign
     * 
     * @param characterEncoding
     * @param param
     * @param key
     * @return
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static String createSign(Map<String, String> param, String key) {
	// 签名步骤一：按字典排序参数
	List list = new ArrayList(param.keySet());
	Object[] ary = list.toArray();
	Arrays.sort(ary);
	list = Arrays.asList(ary);
	String str = "";
	for (int i = 0; i < list.size(); i++) {
	    str += list.get(i) + "=" + param.get(list.get(i) + "") + "&";
	}
	// 签名步骤二：加上key
	str += "key=" + key;
	// 步骤三：加密并大写
	str = PayUtil.MD5Encode(str, "utf-8").toUpperCase();
	return str;
    }

    public static String MD5Encode(String origin, String charsetName) {
	String resultString = null;
	try {
	    resultString = new String(origin);
	    MessageDigest md = MessageDigest.getInstance("MD5");
	    if (UtilValidate.isEmpty(charsetName)) {
		resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
	    } else {
		resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetName)));
	    }
	} catch (Exception e) {

	}
	return resultString;
    }

    public static String byteArrayToHexString(byte b[]) {
	StringBuffer resultSb = new StringBuffer();
	for (int i = 0; i < b.length; i++) {
	    resultSb.append(PayUtil.byteToHexString(b[i]));
	}
	return resultSb.toString();
    }

    public static String byteToHexString(byte b) {
	int n = b;
	if (n < 0) {
	    n += 256;
	}
	int d1 = n / 16;
	int d2 = n % 16;
	return PayUtil.hexDigits[d1] + PayUtil.hexDigits[d2];
    }

    public static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
	    "e", "f" };

}
